package flash_device

import (
	"log"
	"os/exec"
	"strings"
	"sync"
	"test/unit_function/file"
	"time"
)

type ImgArr struct {
	imgArr []string
}

func (obj *ImgArr) getImgInstance() []string {
	once := sync.Once{}
	once.Do(func() {
		obj.imgArr[0] = "boot_linux"
		obj.imgArr[1] = "system"
		obj.imgArr[2] = "vendor"
		obj.imgArr[3] = "userdata"
		obj.imgArr[4] = "resource"
		obj.imgArr[5] = "ramdisk"
		obj.imgArr[6] = "chipset"
		obj.imgArr[7] = "sys-prod"
		obj.imgArr[8] = "chip-prod"
		obj.imgArr[9] = "updater"
	})
	return obj.imgArr
}

// FlashDevice 统一的刷机操作，目前已经完成全部功能
// TODO 1.后面要把全部的log.Fatal改成仅输出日志、发送邮件通知，并让上层重新调用
// TODO 2.要能够兼容已经进入loader状态的设备
func FlashDevice(upgradeToolPath string, imgPath string) {
	// 1.检查是否连接上
	if !checkConnect(5) {
		log.Printf("checkConnect failed\n")
	}
	// 2.进入loader模式
	_, err := exec.Command("hdc", "shell", "reboot loader").Output()
	if err != nil {
		log.Println("reboot error msg=", err)
	}
	time.Sleep(time.Second * 60)
	//3.刷机
	//3.1 刷进MiniLoaderAll.bin
	log.Println("start flash...")
	cmd := upgradeToolPath + " UL " + imgPath + "/MiniLoaderAll.bin -noreset"
	output, err := exec.Command(upgradeToolPath, "UL", imgPath+"/MiniLoaderAll.bin", "-noreset").Output()
	if !strings.Contains(string(output), "Upgrade loader ok") || err != nil {
		log.Fatal(cmd+" execute error, error msg = ", err)
	}
	time.Sleep(time.Second * 3)
	// 3.2 刷进parameter.txt
	cmd = upgradeToolPath + " DI -p " + imgPath + "/parameter.txt"
	output, err = exec.Command(upgradeToolPath, "DI", "-p", imgPath+"/parameter.txt").Output()
	if !strings.Contains(string(output), "Write gpt ok") || err != nil {
		log.Fatal(cmd+"execute error, error msg = ", err)
	}
	time.Sleep(time.Second * 5)
	// 3.3 刷进uboot.img
	cmd = upgradeToolPath + " DI -uboot " + imgPath + "/uboot.img " + imgPath + "/parameter.txt"
	output, err = exec.Command(upgradeToolPath, "DI", "-uboot", imgPath+"/uboot.img", imgPath+"/parameter.txt").Output()
	if !strings.Contains(string(output), "Download image ok") || err != nil {
		log.Fatal(cmd+"execute error, error msg = ", err)
	}
	// 3.4 刷入剩余的img
	imgArr := make([]string, 10)
	imgArr[0] = "boot_linux"
	imgArr[1] = "system"
	imgArr[2] = "vendor"
	imgArr[3] = "userdata"
	imgArr[4] = "resource"
	imgArr[5] = "ramdisk"
	imgArr[6] = "chipset"
	imgArr[7] = "sys-prod"
	imgArr[8] = "chip-prod"
	imgArr[9] = "updater"
	for i, s := range imgArr {
		// 先判断是否存在，如果镜像不存在就直接打印日志
		filename := imgPath + "/" + s + ".img"
		if !file.FileExists(filename) {
			log.Printf("[%d/9] %s is not exist, ignore\n", i, filename)
			continue
		}
		// 刷入
		cmd = upgradeToolPath + " DI -" + s + " " + filename
		output, err = exec.Command(upgradeToolPath, "DI", "-"+s, filename).Output()
		if !strings.Contains(string(output), "Download image ok") || err != nil {
			log.Printf("[%d/9] try download %s again\n", i, s)
			time.Sleep(time.Second * 3)
			output, err = exec.Command(upgradeToolPath, "DI", "-"+s, filename).Output()
			if !strings.Contains(string(output), "Download image ok") || err != nil {
				log.Fatal(cmd+"execute error, error msg = ", err)
			}
		}
		log.Printf("[%d/9] download %s successfully!\n", i, s)
	}
	// 3.5 重启
	log.Println("restarting device...")
	_, err = exec.Command(upgradeToolPath, "RD").Output()
	if err != nil {
		log.Fatal("restart failed errorMsg=", err)
	}
	log.Println("restart success")
}

// 调用场景：1.在程序启动之前判断是否已经连接上
// 调用场景：2.运行到flash操作时判断是否已经连接上

// 逻辑：1.先判断是否已经连接上，如果没连接上，那就直接通报邮件，并返回false
func checkConnect(times int) bool {
	for i := 0; i < times; i++ {
		output, err := exec.Command("hdc", "shell", "exit").Output()
		if !strings.Contains(string(output), "Fail") && err == nil {
			return true
		}
	}
	// TODO 发送邮件通知

	return false
}
